home *** CD-ROM | disk | FTP | other *** search
/ Personal Computer World 2008 February / PCWFEB08.iso / Software / Freeware / Miro 1.0 / Miro_Installer.exe / xulrunner / chrome / toolkit.jar / content / global / findBar.js < prev    next >
Encoding:
Text File  |  2005-10-20  |  23.2 KB  |  845 lines

  1. //@line 40 "/c/mozilla/toolkit/components/typeaheadfind/content/findBar.js"
  2.  
  3. const FIND_NORMAL = 0;
  4. const FIND_TYPEAHEAD = 1;
  5. const FIND_LINKS = 2;
  6.  
  7. const CHAR_CODE_SPACE = " ".charCodeAt(0);
  8. const CHAR_CODE_SLASH = "/".charCodeAt(0);
  9. const CHAR_CODE_APOSTROPHE = "'".charCodeAt(0);
  10.  
  11. // Global find variables
  12. var gFindMode = FIND_NORMAL;
  13. var gFoundLink = null;
  14. var gCurrentWindow = null;
  15. var gTmpOutline = null;
  16. var gTmpOutlineOffset = "0";
  17. var gDrawOutline = false;
  18. var gQuickFindTimeout = null;
  19. var gQuickFindTimeoutLength = 0;
  20. var gHighlightTimeout = null;
  21. var gUseTypeAheadFind = false;
  22. var gWrappedToTopStr = "";
  23. var gWrappedToBottomStr = "";
  24. var gNotFoundStr = "";
  25. var gFlashFindBar = 0;
  26. var gFlashFindBarCount = 6;
  27. var gFlashFindBarTimeout = null;
  28. var gLastHighlightString = "";
  29. var gTypeAheadLinksOnly = false;
  30. var gIsIMEComposing = false;
  31. var gTextToSubURIService = null;
  32.  
  33. // DOMRange used during highlighting
  34. var searchRange;
  35. var startPt;
  36. var endPt;
  37.  
  38. var gTypeAheadFind = {
  39.   useTAFPref: "accessibility.typeaheadfind",
  40.   searchLinksPref: "accessibility.typeaheadfind.linksonly",
  41.   
  42.   observe: function(aSubject, aTopic, aPrefName)
  43.   {
  44.     if (aTopic != "nsPref:changed" || (aPrefName != this.useTAFPref && aPrefName != this.searchLinksPref))
  45.       return;
  46.  
  47.     var prefService = Components.classes["@mozilla.org/preferences-service;1"]
  48.                                 .getService(Components.interfaces.nsIPrefBranch);
  49.       
  50.     gUseTypeAheadFind = prefService.getBoolPref("accessibility.typeaheadfind");
  51.     gTypeAheadLinksOnly = gPrefService.getBoolPref("accessibility.typeaheadfind.linksonly");
  52.   }
  53. };
  54.  
  55. function initFindBar()
  56. {
  57.   getBrowser().addEventListener("keypress", onBrowserKeyPress, false);
  58.   getBrowser().addEventListener("mouseup", onBrowserMouseUp, false);
  59.   
  60.   var prefService = Components.classes["@mozilla.org/preferences-service;1"]
  61.                               .getService(Components.interfaces.nsIPrefBranch);
  62.  
  63.   var pbi = prefService.QueryInterface(Components.interfaces.nsIPrefBranch2);
  64.  
  65.   gQuickFindTimeoutLength = prefService.getIntPref("accessibility.typeaheadfind.timeout");
  66.   gFlashFindBar = prefService.getIntPref("accessibility.typeaheadfind.flashBar");
  67.  
  68.   pbi.addObserver(gTypeAheadFind.useTAFPref, gTypeAheadFind, false);
  69.   pbi.addObserver(gTypeAheadFind.searchLinksPref, gTypeAheadFind, false);
  70.   gUseTypeAheadFind = prefService.getBoolPref("accessibility.typeaheadfind");
  71.   gTypeAheadLinksOnly = prefService.getBoolPref("accessibility.typeaheadfind.linksonly");
  72.  
  73.   var fastFind = getBrowser().fastFind;
  74.   fastFind.focusLinks = true;
  75.   
  76.   var findField = document.getElementById("find-field");
  77.   findField.addEventListener("dragdrop", findBarOnDrop, true);
  78.  
  79.   gTextToSubURIService =
  80.     Components.classes["@mozilla.org/intl/texttosuburi;1"]
  81.                 .getService(Components.interfaces.nsITextToSubURI);
  82. }
  83.  
  84. var findbarObserver = {
  85.   onDrop: function (aEvent, aXferData, aDragSession)
  86.     {
  87.       var findField = document.getElementById("find-field");
  88.       findField.value = aXferData.data;
  89.       find(aXferData.data);
  90.     },
  91.   getSupportedFlavours: function ()
  92.     {
  93.       var flavourSet = new FlavourSet();
  94.       flavourSet.appendFlavour("text/unicode");
  95.       return flavourSet;
  96.     }
  97. };
  98.  
  99. function uninitFindBar()
  100. {
  101.    var prefService = Components.classes["@mozilla.org/preferences-service;1"]
  102.                                .getService(Components.interfaces.nsIPrefBranch);
  103.  
  104.    var pbi = prefService.QueryInterface(Components.interfaces.nsIPrefBranch2);
  105.    pbi.removeObserver(gTypeAheadFind.useTAFPref, gTypeAheadFind);
  106.    pbi.removeObserver(gTypeAheadFind.searchLinksPref, gTypeAheadFind);
  107.  
  108.    getBrowser().removeEventListener("keypress", onBrowserKeyPress, false);
  109.    getBrowser().removeEventListener("mouseup", onBrowserMouseUp, false);
  110. }
  111.  
  112. function toggleHighlight(aHighlight)
  113. {
  114.   var word = document.getElementById("find-field").value;
  115.   if (aHighlight) {
  116.     highlightDoc('yellow', 'black', word);
  117.   } else {
  118.     highlightDoc(null, null, null);
  119.     gLastHighlightString = null;
  120.   }
  121. }
  122.  
  123. function highlightDoc(highBackColor, highTextColor, word, win)
  124. {
  125.   if (!win)
  126.     win = window._content; 
  127.  
  128.   for (var i = 0; win.frames && i < win.frames.length; i++) {
  129.     highlightDoc(highBackColor, highTextColor, word, win.frames[i]);
  130.   }
  131.  
  132.   var doc = win.document;
  133.   if (!document)
  134.     return;
  135.  
  136.   if (!("body" in doc))
  137.     return;
  138.  
  139.   var body = doc.body;
  140.   
  141.   var count = body.childNodes.length;
  142.   searchRange = doc.createRange();
  143.   startPt = doc.createRange();
  144.   endPt = doc.createRange();
  145.  
  146.   searchRange.setStart(body, 0);
  147.   searchRange.setEnd(body, count);
  148.  
  149.   startPt.setStart(body, 0);
  150.   startPt.setEnd(body, 0);
  151.   endPt.setStart(body, count);
  152.   endPt.setEnd(body, count);
  153.  
  154.   if (!highBackColor) {
  155.     // Remove highlighting.  We use the find API again rather than
  156.     // searching for our span elements by id so that we gain access to the
  157.     // anonymous content that nsIFind searches.
  158.  
  159.     if (!gLastHighlightString)
  160.       return;
  161.  
  162.     var retRange = null;
  163.     var finder = Components.classes["@mozilla.org/embedcomp/rangefind;1"].createInstance()
  164.                          .QueryInterface(Components.interfaces.nsIFind);
  165.  
  166.     while ((retRange = finder.Find(gLastHighlightString, searchRange,startPt, endPt))) {
  167.       var startContainer = retRange.startContainer;
  168.       var elem = null;
  169.       try {
  170.         elem = startContainer.parentNode;
  171.       }
  172.       catch (e) { }
  173.  
  174.       if (elem && elem.getAttribute("id") == "__firefox-findbar-search-id") {
  175.         var child = null;
  176.         var docfrag = doc.createDocumentFragment();
  177.         var next = elem.nextSibling;
  178.         var parent = elem.parentNode;
  179.  
  180.         while ((child = elem.firstChild)) {
  181.           docfrag.appendChild(child);
  182.         }
  183.  
  184.         startPt = doc.createRange();
  185.         startPt.setStartAfter(elem);
  186.  
  187.         parent.removeChild(elem);
  188.         parent.insertBefore(docfrag, next);
  189.         parent.normalize();
  190.       }
  191.       else {
  192.         // Somehow we didn't highlight this instance; just skip it.
  193.         startPt = doc.createRange();
  194.         startPt.setStart(retRange.endContainer, retRange.endOffset);
  195.       }
  196.  
  197.       startPt.collapse(true);
  198.     }
  199.     return;
  200.   }
  201.  
  202.   var baseNode = doc.createElement("span");
  203.   baseNode.setAttribute("style", "background-color: " + highBackColor + "; color: " + highTextColor + ";"
  204.                                    + "display: inline; font-size: inherit; padding: 0;");
  205.   baseNode.setAttribute("id", "__firefox-findbar-search-id");
  206.  
  207.   highlightText(word, baseNode);
  208. }
  209.  
  210. function highlightText(word, baseNode)
  211. {
  212.   var retRange = null;
  213.   var finder = Components.classes["@mozilla.org/embedcomp/rangefind;1"].createInstance()
  214.                          .QueryInterface(Components.interfaces.nsIFind);
  215.  
  216.   finder.caseSensitive = document.getElementById("find-case-sensitive").checked;
  217.  
  218.   while((retRange = finder.Find(word, searchRange, startPt, endPt))) {
  219.     // Highlight
  220.     var nodeSurround = baseNode.cloneNode(true);
  221.     var node = highlight(retRange, nodeSurround);
  222.     startPt = node.ownerDocument.createRange();
  223.     startPt.setStart(node, node.childNodes.length);
  224.     startPt.setEnd(node, node.childNodes.length);
  225.   }
  226.   
  227.   gLastHighlightString = word;
  228. }
  229.  
  230. function highlight(range, node)
  231. {
  232.   var startContainer = range.startContainer;
  233.   var startOffset = range.startOffset;
  234.   var endOffset = range.endOffset;
  235.   var docfrag = range.extractContents();
  236.   var before = startContainer.splitText(startOffset);
  237.   var parent = before.parentNode;
  238.   node.appendChild(docfrag);
  239.   parent.insertBefore(node, before);
  240.   return node;
  241. }
  242.  
  243. function getSelectionControllerForFindToolbar(ds)
  244. {
  245.   try {
  246.     var display = ds.QueryInterface(Components.interfaces.nsIInterfaceRequestor).getInterface(Components.interfaces.nsISelectionDisplay);
  247.   }
  248.   catch (e) { return null; }
  249.   return display.QueryInterface(Components.interfaces.nsISelectionController);
  250. }
  251.  
  252. function toggleCaseSensitivity(aCaseSensitive)
  253. {
  254.   var fastFind = getBrowser().fastFind;
  255.   fastFind.caseSensitive = aCaseSensitive;
  256.   
  257.   if (gFindMode != FIND_NORMAL)
  258.     setFindCloseTimeout();
  259. }
  260.   
  261. function changeSelectionColor(aAttention)
  262. {
  263.   try {
  264.     var ds = getBrowser().docShell;
  265.   } catch(e) {
  266.     // If we throw here, the browser we were in is already destroyed.
  267.     // See bug 273200.
  268.     return;
  269.   }
  270.   var dsEnum = ds.getDocShellEnumerator(Components.interfaces.nsIDocShellTreeItem.typeContent,
  271.                                         Components.interfaces.nsIDocShell.ENUMERATE_FORWARDS);
  272.   while (dsEnum.hasMoreElements()) {
  273.     ds = dsEnum.getNext().QueryInterface(Components.interfaces.nsIDocShell);
  274.     var controller = getSelectionControllerForFindToolbar(ds);
  275.     if (!controller)
  276.       continue;
  277.     const selCon = Components.interfaces.nsISelectionController;
  278.     controller.setDisplaySelection(aAttention? selCon.SELECTION_ATTENTION : selCon.SELECTION_ON);
  279.   }
  280. }
  281.  
  282. function openFindBar()
  283. {
  284.   if (!gNotFoundStr || !gWrappedToTopStr || !gWrappedToBottomStr) {
  285.     var bundle = document.getElementById("bundle_findBar");
  286.     gNotFoundStr = bundle.getString("NotFound");
  287.     gWrappedToTopStr = bundle.getString("WrappedToTop");
  288.     gWrappedToBottomStr = bundle.getString("WrappedToBottom");
  289.   }
  290.  
  291.   var findToolbar = document.getElementById("FindToolbar");
  292.   if (findToolbar.hidden) {
  293.     findToolbar.hidden = false;
  294.   
  295.     var statusIcon = document.getElementById("find-status-icon");
  296.     var statusText = document.getElementById("find-status");
  297.     var findField = document.getElementById("find-field");
  298.     findField.removeAttribute("status");
  299.     statusIcon.removeAttribute("status");
  300.     statusText.value = "";
  301.  
  302.     return true;
  303.   }
  304.   return false;
  305. }
  306.  
  307. function focusFindBar()
  308. {
  309.   var findField = document.getElementById("find-field");
  310.   findField.focus();    
  311. }
  312.  
  313. function selectFindBar()
  314. {
  315.   var findField = document.getElementById("find-field");
  316.   findField.select();    
  317. }
  318.  
  319. function closeFindBar()
  320. {
  321.   // ensure the dom is ready...
  322.   setTimeout(delayedCloseFindBar, 0);
  323. }
  324.  
  325. function fireKeypressEvent(target, evt)
  326. {
  327.   if (!target)
  328.     return;
  329.   var event = document.createEvent("KeyEvents");
  330.   event.initKeyEvent(evt.type, evt.canBubble, evt.cancelable,
  331.                      evt.view, evt.ctrlKey, evt.altKey, evt.shiftKey,
  332.                      evt.metaKey, evt.keyCode, evt.charCode);
  333.   target.dispatchEvent(event);
  334. }
  335.  
  336. function updateStatusBarFind()
  337. {
  338.   var xulBrowserWindow = window.XULBrowserWindow;
  339.   if (!xulBrowserWindow)
  340.     return false;
  341.  
  342.   if (!gFoundLink || !gFoundLink.href || gFoundLink.href == "") {
  343.     xulBrowserWindow.setOverLink("");
  344.     return true;
  345.   }
  346.  
  347.   var docCharset = "";
  348.   var ownerDoc = gFoundLink.ownerDocument;
  349.   if (ownerDoc)
  350.     docCharset = ownerDoc.characterSet;
  351.  
  352.   var url =
  353.     gTextToSubURIService.unEscapeURIForUI(docCharset, gFoundLink.href);
  354.   xulBrowserWindow.setOverLink(url);
  355.  
  356.   return true;
  357. }
  358.  
  359. function setFoundLink(foundLink)
  360. {
  361.   if (gFoundLink == foundLink)
  362.     return;
  363.  
  364.   if (gFoundLink && gDrawOutline) {
  365.     // restore original outline
  366.     gFoundLink.style.outline = gTmpOutline;
  367.     gFoundLink.style.outlineOffset = gTmpOutlineOffset;
  368.   }
  369.   gDrawOutline = (foundLink && gFindMode != FIND_NORMAL);
  370.   if (gDrawOutline) {
  371.     // backup original outline
  372.     gTmpOutline = foundLink.style.outline;
  373.     gTmpOutlineOffset = foundLink.style.outlineOffset;
  374.     // draw pseudo focus rect
  375.     // XXX Should we change the following style for FAYT pseudo focus?
  376.     // XXX Shouldn't we change default design if outline is visible already?
  377.     foundLink.style.outline = "1px dotted invert";
  378.     foundLink.style.outlineOffset = "0";
  379.   }
  380.  
  381.   gFoundLink = foundLink;
  382.  
  383.   // We should update status bar. But we need delay. If the mouse cursor is
  384.   // on the document, the status bar text is changed by mouse event that is
  385.   // fired by scroll event. So, we need to change the status bar text after
  386.   // mouse event.
  387.   if (gFindMode != FIND_NORMAL)
  388.     setTimeout(updateStatusBarFind, 0);
  389. }
  390.  
  391. function finishFAYT(aKeypressEvent)
  392. {
  393.   try {
  394.     if (gFoundLink)
  395.       gFoundLink.focus();
  396.     else if (gCurrentWindow)
  397.       gCurrentWindow.focus();
  398.     else
  399.       return false;
  400.   }
  401.   catch(e) {
  402.     return false;
  403.   }
  404.  
  405.   // NOTE: In this time, gFoundLink and gCurrentWindow are set null.
  406.   // Because find toolbar lost focus.
  407.  
  408.   if (aKeypressEvent)
  409.     aKeypressEvent.preventDefault();
  410.  
  411.   closeFindBar();
  412.   return true;
  413. }
  414.  
  415. function delayedCloseFindBar()
  416. {
  417.   var findField = document.getElementById("find-field");
  418.   var findToolbar = document.getElementById("FindToolbar");
  419.   var ww = Components.classes["@mozilla.org/embedcomp/window-watcher;1"]
  420.                      .getService(Components.interfaces.nsIWindowWatcher);
  421.  
  422.   if (window == ww.activeWindow) { 
  423.     var focusedElement = document.commandDispatcher.focusedElement;
  424.     if (focusedElement && focusedElement.parentNode &&
  425.           (focusedElement.parentNode == findToolbar ||
  426.            focusedElement.parentNode.parentNode == findField)) {
  427.       // block scrolling on focus since find already scrolls, further
  428.       // scrolling is due to user action, so don't override this
  429.       var suppressedScroll = document.commandDispatcher.suppressFocusScroll;
  430.       document.commandDispatcher.suppressFocusScroll = true;
  431.       // We MUST reset suppressFocusScroll.
  432.       try {
  433.         if (gFoundLink)
  434.           gFoundLink.focus();
  435.         else if (gCurrentWindow)
  436.           gCurrentWindow.focus();
  437.         else
  438.           window.content.focus();
  439.       }
  440.       catch(e) {
  441.         // Retry to set focus.
  442.         try {
  443.           window.content.focus();
  444.         }
  445.         catch(e) { /* We lose focused element! */ }
  446.       }
  447.       document.commandDispatcher.suppressFocusScroll = suppressedScroll;
  448.     }
  449.   }
  450.  
  451.   findToolbar.hidden = true;
  452.   setFindMode(FIND_NORMAL);
  453.   setFoundLink(null);
  454.   gCurrentWindow = null;
  455.   changeSelectionColor(false);
  456.   if (gQuickFindTimeout) {
  457.     clearTimeout(gQuickFindTimeout);
  458.     gQuickFindTimeout = null;    
  459.   } 
  460. }
  461.  
  462. function shouldFastFind(evt)
  463. {
  464.   if (evt.ctrlKey || evt.altKey || evt.metaKey || evt.getPreventDefault())
  465.     return false;
  466.     
  467.   var elt = document.commandDispatcher.focusedElement;
  468.   if (elt) {
  469.     if (elt instanceof HTMLInputElement) {
  470.       // block FAYT when an <input> textfield element is focused
  471.       var inputType = elt.type;
  472.       switch (inputType) {
  473.         case "text":
  474.         case "password":
  475.         case "file":
  476.           return false;
  477.       }
  478.     }
  479.     else if (elt instanceof HTMLTextAreaElement ||
  480.              elt instanceof HTMLSelectElement ||
  481.              elt instanceof HTMLIsIndexElement)
  482.       return false;
  483.   }
  484.  
  485.   // disable FAYT in about:config and about:blank to prevent FAYT opening
  486.   // unexpectedly - to fix bugs 264562, 267150, 269712
  487.   var url = getBrowser().currentURI.spec;
  488.   if (url == "about:blank" || url == "about:config")
  489.     return false;
  490.  
  491.   var win = document.commandDispatcher.focusedWindow;
  492.   if (win && win.document.designMode == "on")
  493.     return false;
  494.   
  495.   return true;
  496. }
  497.  
  498. function onFindBarBlur()
  499. {
  500.   changeSelectionColor(false);
  501.   setFoundLink(null);
  502.   gCurrentWindow = null;
  503. }
  504.  
  505. function onBrowserMouseUp(evt)
  506. {
  507.   var findToolbar = document.getElementById("FindToolbar");
  508.   if (!findToolbar.hidden && gFindMode != FIND_NORMAL)
  509.     closeFindBar();
  510. }
  511.  
  512. function onBrowserKeyPress(evt)
  513. {
  514.   // Check focused elt
  515.   if (!shouldFastFind(evt))
  516.     return;
  517.  
  518.   var findField = document.getElementById("find-field");
  519.   if (gFindMode != FIND_NORMAL && gQuickFindTimeout) {
  520.     if (!evt.charCode)
  521.       return;
  522.     selectFindBar();
  523.     focusFindBar();
  524.     fireKeypressEvent(findField.inputField, evt);
  525.     evt.preventDefault();
  526.     return;
  527.   }
  528.  
  529.   if (evt.charCode == CHAR_CODE_APOSTROPHE || evt.charCode == CHAR_CODE_SLASH ||
  530.       (gUseTypeAheadFind && evt.charCode && evt.charCode != CHAR_CODE_SPACE)) {
  531.     var findMode = (evt.charCode == CHAR_CODE_APOSTROPHE ||
  532.                     (gTypeAheadLinksOnly && evt.charCode != CHAR_CODE_SLASH))
  533.                    ? FIND_LINKS : FIND_TYPEAHEAD;
  534.     setFindMode(findMode);
  535.     if (openFindBar()) {
  536.       setFindCloseTimeout();
  537.       selectFindBar();
  538.       focusFindBar();
  539.       findField.value = "";
  540.       if (gUseTypeAheadFind &&
  541.           evt.charCode != CHAR_CODE_APOSTROPHE &&
  542.           evt.charCode != CHAR_CODE_SLASH)
  543.         fireKeypressEvent(findField.inputField, evt);
  544.       evt.preventDefault();
  545.     }
  546.     else {
  547.       selectFindBar();
  548.       focusFindBar();
  549.       if (gFindMode != FIND_NORMAL) {
  550.         findField.value = "";
  551.         if (evt.charCode != CHAR_CODE_APOSTROPHE &&
  552.             evt.charCode != CHAR_CODE_SLASH)
  553.           fireKeypressEvent(findField.inputField, evt);
  554.         evt.preventDefault();
  555.       }
  556.     }
  557.   }
  558. }
  559.  
  560. function onFindBarKeyPress(evt)
  561. {
  562.   if (evt.keyCode == KeyEvent.DOM_VK_RETURN) {
  563.     if (gFindMode == FIND_NORMAL) {
  564.       var findString = document.getElementById("find-field");
  565.       if (!findString.value)
  566.         return;
  567.  
  568. //@line 609 "/c/mozilla/toolkit/components/typeaheadfind/content/findBar.js"
  569.       if (evt.ctrlKey) {
  570. //@line 611 "/c/mozilla/toolkit/components/typeaheadfind/content/findBar.js"
  571.         document.getElementById("highlight").click();
  572.         return;
  573.       }
  574.  
  575.       if (evt.shiftKey)
  576.         findPrevious();
  577.       else
  578.         findNext();
  579.     }
  580.     else {
  581.       if (gFoundLink) {
  582.         var tmpLink = gFoundLink;
  583.         if (finishFAYT(evt))
  584.           fireKeypressEvent(tmpLink, evt);
  585.       }
  586.     }
  587.   }
  588.   else if (evt.keyCode == KeyEvent.DOM_VK_TAB) {
  589.     var shouldHandle = !evt.altKey && !evt.ctrlKey && !evt.metaKey;
  590.     if (shouldHandle && gFindMode != FIND_NORMAL && finishFAYT(evt)) {
  591.       if (evt.shiftKey)
  592.         document.commandDispatcher.rewindFocus();
  593.       else
  594.         document.commandDispatcher.advanceFocus();
  595.     }
  596.   }
  597.   else if (evt.keyCode == KeyEvent.DOM_VK_ESCAPE) {
  598.     closeFindBar();
  599.     evt.preventDefault();
  600.   } 
  601.   else if (evt.keyCode == KeyEvent.DOM_VK_PAGE_UP) {
  602.     window.top._content.scrollByPages(-1);
  603.     evt.preventDefault();
  604.   }
  605.   else if (evt.keyCode == KeyEvent.DOM_VK_PAGE_DOWN) {
  606.     window.top._content.scrollByPages(1);
  607.     evt.preventDefault();
  608.   }
  609.   else if (evt.keyCode == KeyEvent.DOM_VK_UP) {
  610.     window.top._content.scrollByLines(-1);
  611.     evt.preventDefault();
  612.   }
  613.   else if (evt.keyCode == KeyEvent.DOM_VK_DOWN) {
  614.     window.top._content.scrollByLines(1);
  615.     evt.preventDefault();
  616.   }
  617.  
  618.  
  619. function enableFindButtons(aEnable)
  620. {
  621.   var findNext = document.getElementById("find-next");
  622.   var findPrev = document.getElementById("find-previous");  
  623.   var highlight = document.getElementById("highlight");
  624.   findNext.disabled = findPrev.disabled = highlight.disabled = !aEnable;  
  625. }
  626.  
  627. function updateFoundLink(res)
  628. {
  629.   var val = document.getElementById("find-field").value;
  630.   if (res == Components.interfaces.nsITypeAheadFind.FIND_NOTFOUND || !val) {
  631.     setFoundLink(null);
  632.     gCurrentWindow = null;
  633.   } else {
  634.     setFoundLink(getBrowser().fastFind.foundLink);
  635.     gCurrentWindow = getBrowser().fastFind.currentWindow;
  636.   }
  637. }
  638.  
  639. function find(val)
  640. {
  641.   if (!val)
  642.     val = document.getElementById("find-field").value;
  643.  
  644.   enableFindButtons(val);
  645.  
  646.   var highlightBtn = document.getElementById("highlight");
  647.   if (highlightBtn.checked)
  648.     setHighlightTimeout();
  649.  
  650.   changeSelectionColor(true);
  651.  
  652.   var fastFind = getBrowser().fastFind;
  653.   var res = fastFind.find(val, gFindMode == FIND_LINKS);
  654.   updateFoundLink(res);
  655.   updateStatus(res, true);
  656.  
  657.   if (gFindMode != FIND_NORMAL)
  658.     setFindCloseTimeout();
  659. }
  660.  
  661. function flashFindBar()
  662. {
  663.   var findToolbar = document.getElementById("FindToolbar");
  664.   if (gFlashFindBarCount-- == 0) {
  665.     clearInterval(gFlashFindBarTimeout);
  666.     findToolbar.removeAttribute("flash");
  667.     gFlashFindBarCount = 6;
  668.     return;
  669.   }
  670.  
  671.   findToolbar.setAttribute("flash", (gFlashFindBarCount % 2 == 0) ? "false" : "true");
  672. }
  673.  
  674. function onFindCmd()
  675. {
  676.   setFindMode(FIND_NORMAL);
  677.   openFindBar();
  678.   if (gFlashFindBar) {
  679.     gFlashFindBarTimeout = setInterval(flashFindBar, 500);
  680.     var prefService = Components.classes["@mozilla.org/preferences-service;1"]
  681.                                 .getService(Components.interfaces.nsIPrefBranch);
  682.  
  683.     prefService.setIntPref("accessibility.typeaheadfind.flashBar", --gFlashFindBar);
  684.   }
  685.   selectFindBar();
  686.   focusFindBar();
  687. }
  688.  
  689. function onFindAgainCmd()
  690. {
  691.   var findString = getBrowser().findString;
  692.   if (!findString) {
  693.     onFindCmd();
  694.     return;
  695.   }
  696.  
  697.   var res = findNext();
  698.   if (res == Components.interfaces.nsITypeAheadFind.FIND_NOTFOUND) {
  699.     if (openFindBar()) {
  700.       focusFindBar();
  701.       selectFindBar();
  702.       if (gFindMode != FIND_NORMAL)
  703.         setFindCloseTimeout();
  704.       
  705.       updateStatus(res, true);
  706.     }
  707.   }
  708. }
  709.  
  710. function onFindPreviousCmd()
  711. {
  712.   var findString = getBrowser().findString;
  713.   if (!findString) {
  714.     onFindCmd();
  715.     return;
  716.   }
  717.  
  718.   var res = findPrevious();
  719.   if (res == Components.interfaces.nsITypeAheadFind.FIND_NOTFOUND) {
  720.     if (openFindBar()) {
  721.       focusFindBar();
  722.       selectFindBar();
  723.       if (gFindMode != FIND_NORMAL)
  724.         setFindCloseTimeout();
  725.       
  726.       updateStatus(res, false);
  727.     }
  728.   }
  729. }
  730.  
  731. function setHighlightTimeout()
  732. {
  733.   if (gHighlightTimeout)
  734.     clearTimeout(gHighlightTimeout);
  735.   gHighlightTimeout = setTimeout(function() { toggleHighlight(false); toggleHighlight(true); }, 500);  
  736. }
  737.  
  738. function isFindBarVisible()
  739. {
  740.   var findBar = document.getElementById("FindToolbar");
  741.   return !findBar.hidden;
  742. }
  743.  
  744. function findNext()
  745. {
  746.   changeSelectionColor(true);
  747.  
  748.   var fastFind = getBrowser().fastFind; 
  749.   var res = fastFind.findNext();  
  750.   updateFoundLink(res);
  751.   updateStatus(res, true);
  752.  
  753.   if (gFindMode != FIND_NORMAL && isFindBarVisible())
  754.     setFindCloseTimeout();
  755.  
  756.   return res;
  757. }
  758.  
  759. function findPrevious()
  760. {
  761.   changeSelectionColor(true);
  762.  
  763.   var fastFind = getBrowser().fastFind;
  764.   var res = fastFind.findPrevious();
  765.   updateFoundLink(res);
  766.   updateStatus(res, false);
  767.  
  768.   if (gFindMode != FIND_NORMAL && isFindBarVisible())
  769.     setFindCloseTimeout();
  770.  
  771.   return res;
  772. }
  773.  
  774. function updateStatus(res, findNext)
  775. {
  776.   var findBar = document.getElementById("FindToolbar");
  777.   var field = document.getElementById("find-field");
  778.   var statusIcon = document.getElementById("find-status-icon");
  779.   var statusText = document.getElementById("find-status");
  780.   switch(res) {
  781.     case Components.interfaces.nsITypeAheadFind.FIND_WRAPPED:
  782.       statusIcon.setAttribute("status", "wrapped");      
  783.       statusText.value = findNext ? gWrappedToTopStr : gWrappedToBottomStr;
  784.       break;
  785.     case Components.interfaces.nsITypeAheadFind.FIND_NOTFOUND:
  786.       statusIcon.setAttribute("status", "notfound");
  787.       statusText.value = gNotFoundStr;
  788.       field.setAttribute("status", "notfound");      
  789.       break;
  790.     case Components.interfaces.nsITypeAheadFind.FIND_FOUND:
  791.     default:
  792.       statusIcon.removeAttribute("status");      
  793.       statusText.value = "";
  794.       field.removeAttribute("status");
  795.       break;
  796.   }
  797. }
  798.  
  799. function setFindCloseTimeout()
  800. {
  801.   if (gQuickFindTimeout)
  802.     clearTimeout(gQuickFindTimeout);
  803.  
  804.   // Don't close the find toolbar while IME is composing.
  805.   if (gIsIMEComposing) {
  806.     gQuickFindTimeout = null;
  807.     return;
  808.   }
  809.  
  810.   gQuickFindTimeout =
  811.     setTimeout(function() { if (gFindMode != FIND_NORMAL) closeFindBar(); },
  812.                gQuickFindTimeoutLength);
  813. }
  814.  
  815. function findBarOnDrop(evt)
  816. {
  817.     nsDragAndDrop.drop(evt, findbarObserver);
  818. }
  819.  
  820. function onFindBarCompositionStart(evt)
  821. {
  822.   gIsIMEComposing = true;
  823.   // Don't close the find toolbar while IME is composing.
  824.   if (gQuickFindTimeout) {
  825.     clearTimeout(gQuickFindTimeout);
  826.     gQuickFindTimeout = null;
  827.   }
  828. }
  829.  
  830. function onFindBarCompositionEnd(evt)
  831. {
  832.   gIsIMEComposing = false;
  833.   if (gFindMode != FIND_NORMAL && isFindBarVisible())
  834.     setFindCloseTimeout();
  835. }
  836.  
  837. function setFindMode(mode)
  838. {
  839.   if (mode == gFindMode)
  840.     return;
  841.  
  842.   gFindMode = mode;
  843. }
  844.